/******************************************************************************
 *                                                                            *
 *                            Volatile Programming                            *
 *                                 Header.cpp                                 *
 *                                                                            *
 ******************************************************************************
 *                                                                            *
 * By: Volatile Pulse                                                         *
 * What: File that contains the header definitions                            *
 * Date: 06.15.2012                                                           *
 *                                                                            *
 ******************************************************************************/

#include "header.h"

#ifdef _WIN32

void VP_SetConsoleCursor(bool bCursor) {
    CONSOLE_CURSOR_INFO curCursorInfo;
    curCursorInfo.bVisible = bCursor;
    curCursorInfo.dwSize = 1;
    SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &curCursorInfo);
}

void VP_GoToXY(int x, int y) {
    COORD CursorPosition = {x, y};
    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), CursorPosition);
}

void VP_SetConsoleColor(int textColor, int bgColor) {
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), (textColor + (bgColor * 16)));
}

void VP_ClearScreen() {
    CONSOLE_SCREEN_BUFFER_INFO csbi;
    HANDLE hStdOut;
    DWORD count;
    DWORD cellCount;
    COORD homeCoords = { 0, 0 };

    hStdOut = GetStdHandle( STD_OUTPUT_HANDLE );
    if (hStdOut == INVALID_HANDLE_VALUE) return;

    // Get the number of cells in the current buffer
    if (!GetConsoleScreenBufferInfo( hStdOut, &csbi )) return;
    cellCount = csbi.dwSize.X *csbi.dwSize.Y;

    // Fill the entire buffer with spaces
    if (!FillConsoleOutputCharacter(hStdOut,(TCHAR) ' ', cellCount, homeCoords, &count))
        return;

    // Fill the entire buffer with the current colors and attributes
    if (!FillConsoleOutputAttribute(hStdOut, csbi.wAttributes, cellCount, homeCoords, &count))
        return;

    // Move the cursor home
    SetConsoleCursorPosition( hStdOut, homeCoords );
    /* Windows */
}

int VP_GetCh () {
    /* Windows */
    HANDLE hConsole;
    INPUT_RECORD inrec;
    DWORD count, mode;

    // Set the console mode to no-echo, raw input, and no window or mouse events.
    hConsole = GetStdHandle(STD_INPUT_HANDLE);
    if (hConsole == INVALID_HANDLE_VALUE || !GetConsoleMode(hConsole, &mode)|| !SetConsoleMode(hConsole, 0))
        return 0;

    FlushConsoleInputBuffer(hConsole);

    // Get a single key RELEASE
    do {
        ReadConsoleInput(hConsole, &inrec, 1, &count);
    } while ((inrec.EventType != KEY_EVENT) || inrec.Event.KeyEvent.bKeyDown);

    // Restore the original console mode
    SetConsoleMode(hConsole, mode);

    return inrec.Event.KeyEvent.wVirtualKeyCode;
    /* Windows */
}

#endif

/* POSIX * /
#include <unistd.h>
#include <term.h>

void ClearScreen() {
   if (!cur_term) {
      int result;
      setupterm( NULL, STDOUT_FILENO, &result );
      if (result <= 0) return;
   }

   putp( tigetstr( "clear" ) );
}
/ * POSIX */

/* ---------------------------------------------------------------------------
 * PressAnyKey()
 * ---------------------------------------------------------------------------
 * Copyright 2008 Michael Thomas Greer
 * http://www.boost.org/LICENSE_1_0.txt
 *
 * function
 *   Optionally print a message and and wait for the user to press (and
 *   release) a single key.
 *
 * arguments
 *   The message to print. If NULL, uses a default message. Specify the empty
 *   string "" to not print anything.
 *
 * returns
 *   The keycode for the key that was pressed.
 *
 *   Extended key codes (like arrow keys) are properly handled, but their
 *   keycode is not understood; they are simply returned as the last code in
 *   the sequence, negated. For example, it is likely that the arrow keys are:
 *
 *     UP_ARROW    = -'A' = -65
 *     DOWN_ARROW  = -'B' = -66
 *     RIGHT_ARROW = -'C' = -67
 *     LEFT_ARROW  = -'D' = -68
 *
 *   Exactly identifying the values for these keys requires a foray into the
 *   terminfo database, which is a subject for later. For now we'll leave it
 *   at this.
 */

/* POSIX * /
#include <stdio.h>
#include <unistd.h>
#include <termios.h>

int PressAnyKey( const char* prompt )
{
#define MAGIC_MAX_CHARS 18
struct termios initial_settings;
struct termios settings;
unsigned char  keycodes[ MAGIC_MAX_CHARS ];
int            count;

tcgetattr( STDIN_FILENO, &initial_settings );
settings = initial_settings;

/ * Set the console mode to no-echo, raw input. * /
/ * The exact meaning of all this jazz will be discussed later. * /
settings.c_cc[ VTIME ] = 1;
settings.c_cc[ VMIN  ] = MAGIC_MAX_CHARS;
settings.c_iflag &= ~(IXOFF);
settings.c_lflag &= ~(ECHO | ICANON);
tcsetattr( STDIN_FILENO, TCSANOW, &settings );

printf( "%s", prompt ? prompt : "Press a key to continue..." );
count = read( stdin, (void*)keycodes, MAGIC_MAX_CHARS );

tcsetattr( STDIN_FILENO, TCSANOW, &initial_settings );

return (count == 1)
     ? keycodes[ 0 ]
     : -(int)(keycodes[ count -1 ]);
}
/ * POSIX */

/* #if defined(__cplusplus)
#include <string>
inline int PressAnyKey( const std::string& prompt = "Press a key to continue..." )
  {
  return PressAnyKey( prompt.c_str() );
  }
#endif */
